#include <cstdio>
#include <mutex>

#include <refbase.h>

class IObjectListener : public RefBase {
public:
    virtual ~IObjectListener() = default;
    virtual void OnObjectChange() = 0;
};

class Object : public RefBase {
public:
    Object()                   { printf("ctor\n"); }
    virtual ~Object() override { printf("dtor\n"); }

    void Set(int i)
    {
        if (i != i_) {
            i_ = i;
            if (listener != nullptr) {
                auto slistener = listener.promote();
                slistener->OnObjectChange();
            }
        }
    }

    int Get()
    {
        return i_;
    }

    void ListenObjectChange(sptr<IObjectListener> &listener)
    {
        this->listener = listener;
    }

private:
    int i_;
    wptr<IObjectListener> listener = nullptr;
};

class ObjectListener : public IObjectListener {
public:
    ObjectListener(const sptr<Object> &obj)
    {
        object = obj;
    }

    void OnObjectChange() override
    {
        printf("listener: %d\n", object->Get());
    }

private:
    sptr<Object> object = nullptr;
};

class Singleton : public RefBase {
public:
    static sptr<Singleton> GetInstance()
    {
        if (instance == nullptr) {
            static std::mutex mutex;
            std::lock_guard<std::mutex> lock(mutex);
            if (instance == nullptr) {
                instance = new Singleton();
            }
        }
        return instance;
    }

    void Func()
    {
        printf("func\n");
    }

private:
    Singleton() = default;
    virtual ~Singleton() = default;
    static inline sptr<Singleton> instance = nullptr;
};

int main()
{
    printf("1\n");
    {
        sptr<Object> obj = new Object();
        printf("2\n");

        obj->Set(0);
        sptr<IObjectListener> listener = new ObjectListener(obj);
        obj->ListenObjectChange(listener);

        printf("3\n");
        obj->Set(10);
        printf("4\n");
    }
    printf("5\n");

    Singleton::GetInstance()->Func();
    return 0;
}
